package com.freely.data.network;

import android.util.Log;

import com.freely.data.network.webSocket.ClosedListener;
import com.freely.data.network.webSocket.ClosingListener;
import com.freely.data.network.webSocket.FailureListener;
import com.freely.data.network.webSocket.MessageListener;
import com.freely.data.network.webSocket.OpenListener;
import com.freely.ui.util.ErrorUtil;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;

import java.net.SocketException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import io.reactivex.Observable;
import io.reactivex.schedulers.Schedulers;
import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;
import okio.ByteString;

/**
 * @author DaWan
 * @time 2018/11/28 15:17
 * @dscription
 */
public class FreelyWebSocketManager extends WebSocketListener {
	private static final String TAG = "FreelyWebSocketManager";
	private List<OpenListener> openListeners = new ArrayList<>();
	private List<MessageListener> messageListeners = new ArrayList<>();
	private List<ClosingListener> closingListeners = new ArrayList<>();
	private List<ClosedListener> closedListeners = new ArrayList<>();
	private List<FailureListener> failureListeners = new ArrayList<>();

	@Override
	public void onOpen(WebSocket webSocket, Response response) {
		Log.d(TAG, "onOpen: ");
		boolean result;
		for (OpenListener listener : openListeners) {
			result = listener.onOpen(webSocket, response);
			if (result) return;
			;
		}
	}

	@Override
	public void onMessage(WebSocket webSocket, String text) {
		Log.d(TAG, "onMessage:" + text);
		boolean result;
		JsonObject jsonObject = FreelyClient.getGson().fromJson(text,JsonObject.class);
		int dataType = jsonObject.getAsJsonPrimitive("data_type").getAsInt();
		if (dataType == -1) {
			String error = jsonObject.getAsJsonPrimitive("data").getAsString();
			ErrorUtil.errorHint(new ServerException(error));
			return;
		}
		if (dataType == 200) {
			String message = jsonObject.getAsJsonPrimitive("data").getAsString();
			Log.d(TAG, "onMessage: 200 = " + message);
			return;
		}
		JsonElement element = jsonObject.get("data");
		for (MessageListener listener : messageListeners) {
			result = listener.onMessage(dataType, element);
			if (result) return;
		}
	}

	@Override
	public void onMessage(WebSocket webSocket, ByteString bytes) {
		Log.d(TAG, "onMessage: ByteString");
	}

	@Override
	public void onClosing(WebSocket webSocket, int code, String reason) {
		Log.d(TAG, "onClosing: " + reason);
		boolean result;
		for (ClosingListener listener : closingListeners) {
			result = listener.onClosing(webSocket, code, reason);
			if (result) return;
		}
	}

	@Override
	public void onClosed(WebSocket webSocket, int code, String reason) {
		Log.d(TAG, "onClosed: " + reason);
		boolean result;
		for (ClosedListener listener : closedListeners) {
			result = listener.onClosed(webSocket, code, reason);
			if (result) return;
		}
	}

	@Override
	public void onFailure(WebSocket webSocket, Throwable t, @Nullable Response response) {
		Log.e(TAG, "onFailure: ", t);
		Observable.just(t)
				.filter(throwable -> throwable instanceof SocketException)
				.delay(5, TimeUnit.SECONDS, Schedulers.trampoline())
				.subscribe(throwable -> {
					Log.d(TAG, "onFailure: webSocket正在重连...");
					FreelyClient.connectionWebSocket();
				})
				.dispose();
		boolean result;
		for (FailureListener listener : failureListeners) {
			result = listener.onFailure(webSocket, t, response);
			if (result) return;
		}
	}

	public void addListener(@NonNull OpenListener listener) {
		openListeners.add(listener);
	}

	public void addListener(@NonNull MessageListener listener) {
		messageListeners.add(listener);
	}

	public void addListener(@NonNull ClosingListener listener) {
		closingListeners.add(listener);
	}

	public void addListener(@NonNull ClosedListener listener) {
		closedListeners.add(listener);
	}

	public void addListener(@NonNull FailureListener listener) {
		failureListeners.add(listener);
	}

	public void removeListener(@NonNull OpenListener listener) {
		openListeners.remove(listener);
	}

	public void removeListener(@NonNull MessageListener listener) {
		messageListeners.remove(listener);
	}

	public void removeListener(@NonNull ClosingListener listener) {
		closingListeners.remove(listener);
	}

	public void removeListener(@NonNull ClosedListener listener) {
		closedListeners.remove(listener);
	}

	public void removeListener(@NonNull FailureListener listener) {
		failureListeners.remove(listener);
	}

	public void clearOpenListener() {
		openListeners.clear();
	}

	public void clearMessageListener() {
		messageListeners.clear();
	}

	public void clearClosingListener() {
		closingListeners.clear();
	}

	public void clearClosedListener() {
		closedListeners.clear();
	}

	public void clearFailureListener() {
		failureListeners.clear();
	}

	public void clearAll() {
		openListeners.clear();
		messageListeners.clear();
		closingListeners.clear();
		closedListeners.clear();
		failureListeners.clear();
	}
}
